package cn.ld.module.system.convert.oauth2;

import cn.hutool.core.date.LocalDateTimeUtil;
import cn.ld.framework.common.core.KeyValue;
import cn.ld.framework.common.enums.UserTypeEnum;
import cn.ld.framework.common.util.collection.CollectionUtils;
import cn.ld.framework.common.util.object.BeanUtils;
import cn.ld.framework.security.core.util.SecurityFrameworkUtils;
import cn.ld.module.system.controller.admin.oauth2.vo.open.OAuth2OpenAccessTokenOutVO;
import cn.ld.module.system.controller.admin.oauth2.vo.open.OAuth2OpenAuthorizeInfoOutVO;
import cn.ld.module.system.controller.admin.oauth2.vo.open.OAuth2OpenCheckTokenOutVO;
import cn.ld.module.system.dal.entity.oauth2.OAuth2AccessTokenEntity;
import cn.ld.module.system.dal.entity.oauth2.OAuth2ApproveEntity;
import cn.ld.module.system.dal.entity.oauth2.OAuth2ClientEntity;
import cn.ld.module.system.util.oauth2.OAuth2Utils;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Mapper
public interface OAuth2OpenConvert {

    OAuth2OpenConvert INSTANCE = Mappers.getMapper(OAuth2OpenConvert.class);

    default OAuth2OpenAccessTokenOutVO convert(OAuth2AccessTokenEntity bean) {
        OAuth2OpenAccessTokenOutVO outVO = BeanUtils.toBean(bean, OAuth2OpenAccessTokenOutVO.class);
        outVO.setTokenType(SecurityFrameworkUtils.AUTHORIZATION_BEARER.toLowerCase());
        outVO.setExpiresIn(OAuth2Utils.getExpiresIn(bean.getExpiresTime()));
        outVO.setScope(OAuth2Utils.buildScopeStr(bean.getScopes()));
        return outVO;
    }

    default OAuth2OpenCheckTokenOutVO convert2(OAuth2AccessTokenEntity bean) {
        OAuth2OpenCheckTokenOutVO outVO = BeanUtils.toBean(bean, OAuth2OpenCheckTokenOutVO.class);
        outVO.setExp(LocalDateTimeUtil.toEpochMilli(bean.getExpiresTime()) / 1000L);
        outVO.setUserType(UserTypeEnum.ADMIN.getValue());
        return outVO;
    }

    default OAuth2OpenAuthorizeInfoOutVO convert(OAuth2ClientEntity client, List<OAuth2ApproveEntity> approves) {
        // 构建 scopes
        List<KeyValue<String, Boolean>> scopes = new ArrayList<>(client.getScopes().size());
        Map<String, OAuth2ApproveEntity> approveMap = CollectionUtils.convertMap(approves, OAuth2ApproveEntity::getScope);
        client.getScopes().forEach(scope -> {
            OAuth2ApproveEntity approve = approveMap.get(scope);
            scopes.add(new KeyValue<>(scope, approve != null ? approve.getApproved() : false));
        });
        // 拼接返回
        return new OAuth2OpenAuthorizeInfoOutVO(
                new OAuth2OpenAuthorizeInfoOutVO.Client(client.getName(), client.getLogo()), scopes);
    }

}
